<?php
require_once('TVB/pms/pdes/model/language.php');
require_once('TVB/pms/pdes/model/programme.php');
require_once('TVB/pms/pdes/model/programme_cpl.php');
require_once('TVB/pms/pdes/model/programme_language.php');

class MisProgramme
{
    private $mis_api;
    private $zh_lang_id;
    private $en_lang_id;
    private $mis_programme;
    private $mis_log;
    private $sync_data;
    private $mis_data;
    private $recover_sql = array();
    private $error = array();
    private $receiveJobs = array();
    private $relation = array();
	private $new;
	private $link_list;
	private $change_logs=array();

    public function __construct() /*{{{*/
    {
        $this->zh_lang_id = language::getLanguageID(AC::LANGUAGE_ZH);
        $this->en_lang_id = language::getLanguageID(AC::LANGUAGE_EN);
        $this->mis_api = new MisApi();
    }/*}}}*/

    public function import(array $jobs)/*{{{*/
    {
		$this->link_list = array();
		$this->change_logs = array();

        foreach ($jobs as $job) {
			$this->new = FALSE;
            $mis_pid = $job['PGM_ID'];
            $relation = mis_pdes::getRelation(array('co_code' => $job['CO_CODE'], 'type' => 'programme', 'mis_id' => $mis_pid));

            if (!empty($relation)) {
                $this->importStart($job, $relation[0]['pdes_pid']);
            } else {
				$this->new = TRUE;
                $programme_id = programme_cpl::findPdesProgramme($mis_pid, $job['CO_CODE']);

                if (empty($programme_id)) {
                    $this->error[] = "Programme(mis_pid:{$mis_pid}) is not exists in pdes.";
                } else {
                    foreach ($programme_id as $row) {
                        $this->importStart($job, $row['programme_id']);
                        $rs = mis_pdes::updateRelation($this->relation);
                        if (!$rs) {
                            $this->error[] = 'update relation failure.';
                        }
                    }
                }
            }
        }

        if (!empty($this->error)) {
            return FALSE;
        } else {
            return TRUE;
        }
    }/*}}}*/

    #import one programme
    private function importStart($job, $pdes_pid)/*{{{*/
    {
        $mis_pid = $job['PGM_ID'];
        $this->sync_data = $this->mis_data = $this->recover_sql = array();
        $this->relation = array(
            'co_code' => $job['CO_CODE'],
            'type' => 'programme', 
            'mis_id' => $job['PGM_ID'], 
            'mis_eid' => '', 
            'mis_pid' => $job['PGM_ID'], 
            'pdes_id' => $pdes_pid, 
            'pdes_eid' => '', 
            'pdes_pid' => $pdes_pid,
        );

        Model::$dbo['w']->beginTransaction();
        try {
            #load mis data
            $this->loadMisData($job);
            #import programme
            $this->importProgramme($job, $pdes_pid);

			//$this->__importProgrammeCasts($job, $pdes_pid);

            #import programme ch language
            $this->importProgrammeCnLanguage($pdes_pid);
            
            #import programme en languange
            $this->importProgrammeEnLanguage($pdes_pid);

            #mis log
            $this->misLog($pdes_pid, TRUE);
            
            #set recevie programme 
            $this->setReceiveJob($job);
            
            Model::$dbo['w']->commit();
        } catch (MISException $e) {
            Model::$dbo['w']->rollBack();

            #mis error log
            $this->misLog($pdes_pid, FALSE, $e->getMessage());
            
            $this->error[] = "Import MIS's programme({$job['CO_CODE']}+{$job['PGM_ID']}) failure:" . $e->getMessage();
        }
    }/*}}}*/

    private function importProgramme($job, $pdes_pid)/*{{{*/
    {
        $mis_pid = $job['PGM_ID'];

        #pdes data
        $programme = new programme;
        $pdes_programme = $programme->get($pdes_pid);
        #Is Last Episode On Air Date Time correct?
        if (!is_null($pdes_programme->last_episode_time_onair) && $pdes_programme->last_episode_time_onair <> '0000-00-00 00:00:00' && $pdes_programme->last_episode_time_onair < date('Y-m-d H:i:s')) {
            throw new MISException("Programme({$pdes_pid})'s Last Episode On Air Date Time is expired in pdes.");
        }
        $sync_programme = MisMapping::getMapping('programme', $this->mis_programme);
        $sync_programme->first_episode_time_onair = $sync_programme->first_time_onair; //bug 4169
		$sync_programme->casts = $this->__importProgrammeCasts($job, $pdes_pid);

		//if pdes has these value. System will follow pdes data.
		if(!empty($pdes_programme->first_network_codes) ){
			$sync_programme->first_network_codes = $pdes_programme->first_network_codes;
		}
		if(!empty($pdes_programme->first_episode_time_onair)){
			$sync_programme->first_episode_time_onair = $pdes_programme->first_episode_time_onair;
		}
        $new_programme = Model::diff(clone $pdes_programme, $sync_programme);
        #programme->casts
// bug 4126        
//        $new_programme_casts = $this->importCast($job, $pdes_pid);
//        if (!empty($new_programme_casts)) {
//            $cast_array = is_array(json_decode($pdes_programme->casts, 1)) ? json_decode($pdes_programme->casts, 1) : array();
//            $this->_mergeCast($cast_array, $new_programme_casts);
//            $this->_uniqueCast($cast_array);
//            $new_programme->casts = json_encode($cast_array);
//        }
        #$new_programme_casts = $this->importCast($job, $pdes_pid);
        #$this->_uniqueCast($new_programme_casts); 
        #$new_programme->casts = json_encode($new_programme_casts);

        $new_programme->modified_at = date('Y-m-d H:i:s');
        $new_programme->status = AC::STATUS_NEW; //bug 4181

		if ($this->new === TRUE) {
			$rs = Model::$dbo['w']->save($new_programme);
			if (!$rs) {
				throw new MISException("Import programme({$pdes_pid}) to pdes error.");
			}

			# change_log
			$this->change_logs[] = array(
				'type'=>'programme',
				'keys'=>array('id'=>$pdes_pid),
				'is_active'=>1,
				'is_publish'=>0,
				'programme_id'=>$pdes_pid
			);
		}

        //$this->sync_data['programme'] = MisMapping::getUIMapping('programme', (array) $pdes_programme);
        $this->sync_data['programme'] = MisMapping::formatLogData('programme', (array) $pdes_programme);
        //$this->mis_data['programme'] = MisMapping::getUIMapping('programme', (array) $sync_programme);
        $this->mis_data['programme'] = MisMapping::formatLogData('programme', (array) $sync_programme);
        //$this->recover_sql[] = MisMapping::getRecoverSql('programme', $pdes_programme);  

        #import programme-tvbcom_category
        #$this->importProgrammeTvbcomCategory($pdes_pid, $new_programme->cpl_category_id);
    }/*}}}*/

    private function importProgrammeCnLanguage($pdes_pid)/*{{{*/
    {
        $pdes_programme_language_zh = programme_language::getLangProgrammeById($pdes_pid, $this->zh_lang_id);
        $sync_programme_language_zh = MisMapping::getMapping('programme-language', $this->mis_programme, 'zh');
		//if pdes has value, system will follow pdes flow.
		if(!empty($pdes_programme_language_zh->title)){
			$sync_programme_language_zh->title = $pdes_programme_language_zh->title;
		}
        $new_programme_language_zh = Model::diff(clone $pdes_programme_language_zh, $sync_programme_language_zh);
        $new_programme_language_zh->programme_id = $pdes_pid;
        $new_programme_language_zh->language_id = $this->zh_lang_id;

		if ($this->new === TRUE) {
			$rs = Model::$dbo['w']->save_by_fields($new_programme_language_zh, array('programme_id', 'language_id'));
			if (!$rs) {
				throw new MISException("Import programme({$pdes_pid})'s chinese language error.");
			}

			# change_log
			$this->change_logs[] = array(
				'type'=>'programme-language',
				'keys'=>array('programme_id'=>$pdes_pid,'language_id'=>$this->zh_lang_id),
				'is_active'=>1,
				'is_publish'=>0,
				'programme_id'=>$pdes_pid
			);
		}

        //$this->sync_data['programme-language_zh'] = MisMapping::getUIMapping('programme-language', (array) $pdes_programme_language_zh, 'zh'); 
        $this->sync_data['programme-language_zh'] = MisMapping::formatLogData('programme-language', (array) $pdes_programme_language_zh, 'zh'); 
        //$this->mis_data['programme-language_zh'] = MisMapping::getUIMapping('programme-language', (array) $sync_programme_language_zh, 'zh'); 
        $this->mis_data['programme-language_zh'] = MisMapping::formatLogData('programme-language', (array) $sync_programme_language_zh, 'zh'); 
        //$this->recover_sql[] = MisMapping::getRecoverSql('programme-language', $pdes_programme_language_zh, 'zh'); 
    }/*}}}*/

    private function importProgrammeEnLanguage($pdes_pid)/*{{{*/
    {
        $pdes_programme_language_en = programme_language::getLangProgrammeById($pdes_pid, $this->en_lang_id);
        $sync_programme_language_en = MisMapping::getMapping('programme-language', $this->mis_programme, 'en');
		if(!empty($pdes_programme_language_en->title)){
			$sync_programme_language_en->title = $pdes_programme_language_en->title;
		}
        $new_programme_language_en = Model::diff(clone $pdes_programme_language_en, $sync_programme_language_en);
        $new_programme_language_en->programme_id = $pdes_pid;
        $new_programme_language_en->language_id = $this->en_lang_id;

		if ($this->new === TRUE) {
			$rs = Model::$dbo['w']->save_by_fields($new_programme_language_en, array('programme_id', 'language_id'));
			if (!$rs) {
				throw new MISException("Import programme({$pdes_pid})'s english language error.");
			}

			# change_log
			$this->change_logs[] = array(
				'type'=>'programme-language',
				'keys'=>array('programme_id'=>$pdes_pid,'language_id'=>$this->en_lang_id),
				'is_active'=>1,
				'is_publish'=>0,
				'programme_id'=>$pdes_pid
			);
		}

        //$this->sync_data['programme-language_en'] = MisMapping::getUIMapping('programme-language', (array) $pdes_programme_language_en, 'en'); 
        $this->sync_data['programme-language_en'] = MisMapping::formatLogData('programme-language', (array) $pdes_programme_language_en, 'en'); 
        //$this->mis_data ['programme-language_en'] = MisMapping::getUIMapping('programme-language', (array) $sync_programme_language_en, 'en'); 
        $this->mis_data ['programme-language_en'] = MisMapping::formatLogData('programme-language', (array) $sync_programme_language_en, 'en'); 
        //$this->recover_sql[] = MisMapping::getRecoverSql('programme-language', $pdes_programme_language_en, 'en'); 
    }/*}}}*/

    private function importCast($job, $pdes_pid)/*{{{*/
    {
        $mis_pid = $job['PGM_ID'];
        #load mis programme's casts
        $param = array(
            'CO_CODE'   => $job['CO_CODE'],
            'PGM_ID'    => $mis_pid, 
            'START_SEQ' => 1, 
            'NUM'       => 9999
        );
        //$mis_casts = $this->mis_api->getDataByApi('getCastByProgramme', $param);
		$mis_pgm_casts = $this->mis_api->getDataByApi('getPgmDefaultCastsByProgramme',$param);
        //if (empty($mis_casts) || !is_object($mis_casts) || empty($mis_pgm_casts) || !is_object($mis_pgm_casts)) {
        if (empty($mis_pgm_casts) || !is_object($mis_pgm_casts)) {
            throw new MISException("load mis programme's casts failure.");
        } 

        $mis_cast_helper = new MisCastHelper(array(
            'co_code' => $job['CO_CODE'],
            'mis_pid' => $mis_pid, 
            'pdes_pid' => $pdes_pid));
        $programme_cast = array();
		//new apiinsert
		foreach($mis_pgm_casts->children() as $values){
				if($values->PgmCasts!=''){
					$attr = $values->PgmCasts->PgmCast->GROUPS_ID->attributes();
					$group_id = (int)$attr->GROUPS_ID;
            		$cast_role_id = MisMapping::getCastRoleMapping($group_id);
            		$casts = array((string)$values->CASTS_ID => $cast_role_id);
					$pid = (int)$values->attributes()->PID;
					#import
        	   		$mis_cast_helper->import($casts,$pid,'programme');
            		$new_programme_cast = $mis_cast_helper->getInsertedIds();
             		$this->_mergeCast($programme_cast, $new_programme_cast);
            		// bug 4124
        		    $casts_mis_update = $mis_cast_helper->getUpdatedIds();
         		    $this->_mergeCast($programme_cast, $casts_mis_update);
           		  	#error
           		  	$cast_error = $mis_cast_helper->getErrorMessage();
           		  	if (!empty($cast_error)) {
            		$this->error[] = "Import programme({$pdes_pid})'s casts failure:" . $cast_error;
             		}

					$this->link_list = array_merge($this->link_list, $mis_cast_helper->getLinkList());

					# change_log
					$this->change_logs = array_merge($this->change_logs,$mis_cast_helper->getChangeLogs());
				}
		}
		return $programme_cast;
		/*foreach ($mis_casts->children() as $element) {
            $attr = $element->GROUPS_ID->attributes();
            $group_id = (int)$attr->GROUPS_ID;
            $cast_role_id = MisMapping::getCastRoleMapping($group_id);	
            $casts = array((string)$element->CASTS_ID => $cast_role_id);
            #import
            $mis_cast_helper->import($casts);
            $new_programme_cast = $mis_cast_helper->getInsertedIds();
			$this->_mergeCast($programme_cast, $new_programme_cast);
            // bug 4124
            $casts_mis_update = $mis_cast_helper->getUpdatedIds();
			$this->_mergeCast($programme_cast, $casts_mis_update);
            #error
            $cast_error = $mis_cast_helper->getErrorMessage();
            if (!empty($cast_error)) {
                $this->error[] = "Import programme({$pdes_pid})'s casts failure:" . $cast_error;
            }
        }*/
		//var_dump($programme_cast);
        //return $programme_cast;
	
    }/*}}}*/

    private function _mergeCast(&$old_cast, $casts)
    {   
        if (is_array($casts) && !empty($casts)) {
            foreach ($casts as $cast_role_id=>$sub_cast) {
                foreach ($sub_cast as $value) {
                    $old_cast[$cast_role_id][] = $value;
                }
            }
        }
    }

    private function importProgrammeTvbcomCategory($pdes_pid, $cpl_category_id)/*{{{*/
    {
        if ($cpl_category_id) {
            $sql = "SELECT `tvbcom_category_id` FROM `cpl_category`
                WHERE `id`=:id";
            $result = Model::selectBySql($sql, array(':id' => $cpl_category_id));
            if (!empty($result)) {
                $sql = "SELECT MAX(`rank`) AS max FROM `programme-tvbcom_category`
                    WHERE `programme_id`=:programme_id";
                $rank = Model::selectBySql($sql, array(':programme_id' => $pdes_pid));
                if (!empty($rank[0]['max'])) {
                    $next_rank = $rank[0]['max'];
                } else {
                    $next_rank = 1;
                }

                $programme_tvbcom_category  = programme_tvbcom_category::getProgrammeTvbcomCategory($pdes_pid, $result[0]['tvbcom_category_id']);
                if (empty($programme_tvbcom_category)) {
                    $programme_tvbcom_category = new programme_tvbcom_category();
                    $programme_tvbcom_category->programme_id = $pdes_pid;
                    $programme_tvbcom_category->category_id = $result[0]['tvbcom_category_id'];
                    $programme_tvbcom_category->rank = $next_rank;

                    #save
                    $rs = Model::$dbo['w']->save($programme_tvbcom_category);
                    if ($rs<0) {
                        throw new MISException("importProgrammeTvbcomCategory failure.");
                    }

                    #mis_log:sync_data
                    $this->sync_data['programme-tvbcom_category'] = array();
                
                    #mis_log:mis_data
                    $this->mis_data['programme-tvbcom_category'] = array(
                        'Programme ID'      => $pdes_pid,
                        'TVB.COM Category'  => $result[0]['tvbcom_category_id'],
                        'rank'              => $next_rank
                    );
    
                    #mis_log:recover_sql
                    //$this->recover_sql[] = "DELETE FROM `programme-tvbcom_category` WHERE `programme_id` = {$pdes_pid} AND `category_id` = {$result[0]['tvbcom_category_id']}";
                }
            }
        }
    }/*}}}*/

    private function loadMisData($job)/*{{{*/
    {
        $param = array(
            'CO_CODE'   => $job['CO_CODE'],    
            'PGM_ID'    => $job['PGM_ID'],
        );
        $this->mis_programme = $this->mis_api->getDataByApi('getProgrammeDetails', $param);
        if (empty($this->mis_programme) || !is_object($this->mis_programme)) {
            throw new MISException("Load mis programme data error.");
        }
    }/*}}}*/

    private function misLog($pdes_id, $success, $message='')/*{{{*/
    {
        $this->mis_log = (object) array(
            'pdes_id'       => $pdes_id, 
            'type'          => 'programme',
            'sync_data'     => $success ? json_encode($this->sync_data) : json_encode(array()), 
            'mis_data'      => $success ? json_encode($this->mis_data) : json_encode(array()), 
            'status'        => $success ? 1 : 0, 
            'message'       => $message, 
            'recover_sql'   => $success ? json_encode($this->recover_sql) : json_encode(array()), 
            'modified_by'   => CommonUtils::get_user(),
            'modified_at'   => date('Y-m-d H:i:s'),
        );

        $rs = mis_log::update($this->mis_log);
		if ($success && $this->new === FALSE && $rs) {
			$this->link_list[] = sprintf(AC::$mis_view_url, 'programme', $pdes_id);
		}
    }/*}}}*/

    public function getErrorMessage(){/*{{{*/
        return !empty($this->error) ? implode("\n", $this->error) : '';
    }/*}}}*/

    private function setReceiveJob($job)
    {
        $this->receiveJobs = array_merge($this->receiveJobs, array($job));
    }

    public function getReceiveJobs()
    {
        return $this->receiveJobs;
    }

	public function getLinkList()
	{
		return $this->link_list;
	}

	public function getChangeLogs(){
		return $this->change_logs;
	}

	private function __importProgrammeCasts($job, $pdes_pid)
	{
        $new_casts = $this->importCast($job, $pdes_pid);

        $programme = new programme;
        $programme_detail = $programme->get($pdes_pid);

		$old_casts = json_decode($programme_detail->casts, TRUE);
		if (is_array($old_casts)) MisCommon::mergeCast($new_casts, $old_casts);

		MisCommon::uniqueCast($new_casts);

        $programme_detail->casts = json_encode($new_casts);

		if ($this->new === TRUE) {
			$programme->update($programme_detail);
		}

		return $programme_detail->casts;
	}
}
?>
